/*
 * Copyright (C) 2015 Basil Miller
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package devlight.io.library;

import ohos.aafwk.ability.AbilitySlice;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.text.Font;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.Resource;
import ohos.global.resource.ResourceManager;
import ohos.global.resource.WrongTypeException;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Size;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.FileNotFoundException;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

public class ResUtil {

    private static final String TAG = ResUtil.class.getSimpleName();
    private static final int BUFFER_LENGTH = 8192;
    public static final int DEFAULT_ERROR = -1;
    private static final String RAW_FILE_PATH = "entry/resources/rawfile/";
    private static Map<Integer, PixelMap> imageCache = new HashMap();

    /**
     * get the color
     *
     * @param context the context
     * @param id the id
     * @return the color
     */
    public static int getColor(Context context, int id) {
        int result = 0;
        if (context == null) {
            LogUtil.error(TAG, "getColor -> get null context");
            return result;
        }
        ResourceManager manager = context.getResourceManager();
        if (manager == null) {
            LogUtil.error(TAG, "getColor -> get null ResourceManager");
            return result;
        }
        try {
            result = manager.getElement(id).getColor();
        } catch (IOException e) {
            LogUtil.error(TAG, "getColor -> IOException");
        } catch (NotExistException e) {
            LogUtil.error(TAG, "getColor -> NotExistException");
        } catch (WrongTypeException e) {
            LogUtil.error(TAG, "getColor -> WrongTypeException");
        }
        return result;
    }

    /**
     * get the string array
     *
     * @param context the context
     * @param id      the string array id
     * @return the string array
     */
    public static String[] getStringArray(Context context, int id) {
        String[] result = null;
        if (context == null) {
            LogUtil.error(TAG, "getStringArray -> get null context");
            return result;
        }
        ResourceManager manager = context.getResourceManager();
        if (manager == null) {
            LogUtil.error(TAG, "getStringArray -> get null ResourceManager");
            return result;
        }
        try {
            result = manager.getElement(id).getStringArray();
        } catch (IOException e) {
            LogUtil.error(TAG, "getStringArray -> IOException");
        } catch (NotExistException e) {
            LogUtil.error(TAG, "getStringArray -> NotExistException");
        } catch (WrongTypeException e) {
            LogUtil.error(TAG, "getStringArray -> WrongTypeException");
        }
        return result;
    }

    public static Font createFont(Context context, String fontFamily) {
        String path = RAW_FILE_PATH + fontFamily;
        File file = new File(context.getDataDir(), fontFamily);
        try (OutputStream outputStream = new FileOutputStream(file);
             InputStream inputStream = context.getResourceManager().getRawFileEntry(path).openRawFile()) {
            byte[] buffer = new byte[BUFFER_LENGTH];
            int bytesRead = inputStream.read(buffer, 0, BUFFER_LENGTH);
            while (bytesRead != DEFAULT_ERROR) {
                outputStream.write(buffer, 0, bytesRead);
                bytesRead = inputStream.read(buffer, 0, BUFFER_LENGTH);
            }
        } catch (FileNotFoundException exception) {
            LogUtil.error(TAG, "loadFontFromFile -> FileNotFoundException : " + exception.getLocalizedMessage());
        } catch (IOException exception) {
            LogUtil.error(TAG, "loadFontFromFile -> IOException : " + exception.getLocalizedMessage());
        }
        return Optional.of(new Font.Builder(file).setWeight(Font.REGULAR).build()).get();
    }

    public static final ShapeElement getShapeElement(Context context, int shape, int color, float radius) {
        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setShape(shape);
        shapeElement.setRgbColor(RgbColor.fromArgbInt(getColor(context, color)));
        shapeElement.setCornerRadius(radius);
        return shapeElement;
    }

    public static PixelMap createByResourceId(AbilitySlice abilitySlice, int resid, String str) throws IOException, NotExistException {
        if (abilitySlice == null) {
            LogUtil.error(TAG, "createByResourceId but slice is null");
            throw new IOException();
        } else if (imageCache.containsKey(Integer.valueOf(resid))) {
            return imageCache.get(Integer.valueOf(resid));
        } else {
            ResourceManager resourceManager = abilitySlice.getResourceManager();
            if (resourceManager != null) {
                Resource resource = resourceManager.getResource(resid);
                if (resource != null) {
                    ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
                    sourceOptions.formatHint = str;
                    ImageSource create = ImageSource.create(readResource(resource), sourceOptions);
                    resource.close();
                    if (create != null) {
                        ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
                        decodingOptions.desiredSize = new Size(0, 0);
                        decodingOptions.desiredRegion = new ohos.media.image.common.Rect(0, 0, 0, 0);
                        decodingOptions.desiredPixelFormat = PixelFormat.ARGB_8888;
                        PixelMap pixelMap = create.createPixelmap(decodingOptions);
                        imageCache.put(Integer.valueOf(resid), pixelMap);
                        return pixelMap;
                    }
                    LogUtil.error(TAG, "imageSource is null");
                    throw new FileNotFoundException();
                }
                LogUtil.error(TAG, "get resource failed");
                throw new IOException();
            }
            LogUtil.error(TAG, "get resource manager failed");
            throw new IOException();
        }
    }

    private static byte[] readResource(Resource resource) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] bArr = new byte[1024];
        while (true) {
            try {
                int read = resource.read(bArr, 0, 1024);
                if (read == -1) {
                    break;
                }
                byteArrayOutputStream.write(bArr, 0, read);
            } catch (IOException e) {
                LogUtil.error(TAG, "readResource failed " + e.getLocalizedMessage());
            }
        }
        return byteArrayOutputStream.toByteArray();
    }
}
